#pragma once
#ifndef CGenomeInBits_H_
#define CGenomeInBits_H_

#include "bitsOperationUtil.h"
#include "SeedPattern.h"
#include "ReadInBits.h"
#include "LongReadInBits.h"
#include "chromosomeNTdata.h"
#include "GenomeNTdata.h"
#include "boolFlagArray.h"
#include "stdafx.h"
#include <algorithm>
using namespace std;

class CGenomeInBits
{
public:
    CGenomeInBits(unsigned int uiGenomeSize = 0);
    CGenomeInBits(CGenomeNTdata* pGenome);
    ~CGenomeInBits(void);
    // Two arrays to store the chromosome string encoded with bits
    WORD_SIZE* pUpperBits;
    WORD_SIZE* pLowerBits;
    CboolFlagArray* pNBits;
    unsigned int uiGenomeLength;
    unsigned int uiGenomeLengthInWordSize;
    CGenomeNTdata* pGenome; // Don't delete this pointer pointing outside
    // get the wordSize substring encoded in bits and store in upperBits and lowerBits
    CReadInBits getSubstringInBits(unsigned int uiGenomeIndex) const;
    // eliminate the bits beyond read length. Not the length should smaller than word_size
    CReadInBits getSubstringInBits(unsigned int uiGenomeIndex, unsigned int uiSubstringLength) const;
    // Call previous function but return CReadInBits, CLongReadInBits according to present reads <= > 64 bp, as arg reference
    inline void getSubstringInBits(unsigned int uiGenomeIndex, unsigned int uiSubstringLength, CReadInBits& read) const;
    inline void getSubstringInBits(unsigned int uiGenomeIndex, unsigned int uiSubstringLength, CLongReadInBits& read) const;
    // call getSubstringInBits and transform the info to DNA sequence and store in caSubstring
    char* getSubstring(unsigned int uiGenomeIndex);
    // get the substring encoded in bits which is shorter than wordSizea.
    char* getSubstring(unsigned int uiGenomeIndex, unsigned int uiSubstringLength);
    char caSubstring[wordSize * 2 + 1];

    bool fragACGTKmerInBits(CReadInBits& kmerInBits, int startIndex, int kmerLength);
    int allocBitStrSpace(unsigned int uiGenomeSize = 0);
private:
    int initialization(unsigned int uiGenomeSize = 0);
    int encodeJunction(unsigned int ChrID);
};

inline void CGenomeInBits::getSubstringInBits(unsigned int uiGenomeIndex, unsigned int uiSubstringLength, CReadInBits& r) const
{
    r = this->getSubstringInBits(uiGenomeIndex, uiSubstringLength);
};

inline void CGenomeInBits::getSubstringInBits(unsigned int uiGenomeIndex, unsigned int uiSubstringLength, CLongReadInBits& r) const
{
    unsigned int uiEndSubstrGenomeIndex = uiGenomeIndex + max((int)uiSubstringLength, CReadInBits::iReadLength);
    // The check boundary is not tight
    if(uiEndSubstrGenomeIndex < this->uiGenomeLength && CLongReadInBits::canBeEncoded(uiSubstringLength)) {
        unsigned int secondHalfStart = uiSubstringLength - CReadInBits::iReadLength; //May need to be change
        r.first = this->getSubstringInBits(uiGenomeIndex, CReadInBits::iReadLength);
        r.second = this->getSubstringInBits(uiGenomeIndex + secondHalfStart, CReadInBits::iReadLength);
    }
};

#endif


